
/*
 *
 * Copyright (c) 2006 P.J.Leonard
 * 
 * http://www.frinika.com
 * 
 * This file is part of Frinika.
 * 
 * Frinika is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.

 * Frinika is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with Frinika; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package uk.ac.bath.domains.IP;

import uk.ac.bath.environment.Evaluator;
import uk.ac.bath.environment.Fitness;
import uk.ac.bath.environment.View;

/**
 *
 * @author pjl
 */
public class IPEvaluator extends Evaluator implements IPGetter {

    int max_steps;
    CartSimIF sim;
 
    private int num_tries;
    private float thresold;
    private int tryCount;
    Fitness fitness;
    private IPSetupIF setup;


    public IPEvaluator(IPSetupIF setup){
        this(20000,1000,100,setup);
    }
    /**
     *
     * @param max_steps      steps for each simulation to achieve success
     * @param threshold      if any trial is less than this then abort.
     * @param num_tries      number of trials to achieve success
     */
    public IPEvaluator(int max_steps, float threshold, int num_tries, IPSetupIF setup) {
        this.max_steps = max_steps;
        this.num_tries = num_tries;
        this.thresold = threshold;
        tryCount = 0;
        this.setup=setup;
    }

    public void nextEvaluationImpl() {
        sim=setup.newCartSim(currentMachine);
        tryCount = 0;
        fitness = new Fitness(max_steps,0.0f);
    }

    public Fitness tickImpl() {
        sim.tick();
        if (setup.hasFailed(sim)) {


            fitness.addUpperBound(sim.getStepCount());

            if (tryCount >= num_tries || fitness.maxFitness < thresold) {
                fitness.finish();
            } else {
                tryCount++;
                sim=setup.newCartSim(currentMachine);
            }


        } else if (sim.getStepCount() >= max_steps) {

            if (tryCount >= num_tries) {
                fitness.addUpperBound(sim.getStepCount());
                fitness.finish();
                
            } else {
                tryCount++;
                sim=setup.newCartSim(currentMachine);
            }
        } else {
            fitness.addLowerBound(sim.getStepCount());
        }

        return fitness;
    }

    public IPModelIF getModel() {
        if (sim == null ) return  null;
        return sim.getModel();
    }

    @Override
    public View createView() {
        return new IPView(this);
    }

    @Override
    protected void initImpl() {
        sim = null;
        tryCount = 0;
        fitness = null;
    }

    @Override
    public String getStatus() {
        return super.getStatus() + " " + String.format("Tries: %-4d  SubTick: %-7d", tryCount, sim.getStepCount());
    }

    public void restart() {
        //if (sim == null) return;
        sim=setup.newCartSim(currentMachine);
    }

    @Override
    public String reportSetup() {
        return " Evaluator: IP maxSteps , numTries "+max_steps+" " + num_tries+"\n"+
                setup.reportSetup();
    }
}
